package com.xh.demo.commons.utils;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.xh.demo.commons.consts.RConst;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author wen
 * @apiNote SignUtil
 * @since 2021-08-07
 */
@Slf4j
public class SignUtil {

    /**
     * 按参数名升续拼接参数
     */
    public static String concatSignString(HttpServletRequest request) {
        Map<String, String> parameterMap = new HashMap<>();
        request.getParameterMap().forEach((key, value) -> parameterMap.put(key, value[0]));
        return concatSignString(parameterMap);
    }

    public static String concatSignString(Map<String, String> parameterMap) {
        // 按照key升续排序，然后拼接参数
        Set<String> keySet = parameterMap.keySet();
        String[] keyArray = keySet.toArray(new String[0]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            // 或略掉的字段
            if (k.equals(RConst.Str.SIGN)) {
                continue;
            }
            String value = parameterMap.get(k).trim();
            if (value.length() > 0) {
                // 参数值为空，则不参与签名
                sb.append(k).append(RConst.Str.EQUAL)
                        .append(value)
                        .append(RConst.Str.AND);
            }
        }
        return sb.toString();
    }

    public static String sign(HttpServletRequest request, String salt) {
        return MD5Util.encode(concatSignString(request).concat(salt));
    }

    public static String sign(String timestamp, String appKey, String appSecret) {
        return MD5Util.encode(timestamp.concat(appKey).concat(appSecret));
    }

    @Slf4j
    public static class MD5Util {

        private static final String[] HEX_DIGITS = {"0", "1", "2", "3", "4", "5",
                "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

        private static String byteArrayToHexString(byte[] b) {
            StringBuilder sb = new StringBuilder();
            for (byte value : b) sb.append(byteToHexString(value));
            return sb.toString();
        }

        private static String byteToHexString(byte b) {
            int n = b;
            if (n < 0)
                n += 256;
            int d1 = n / 16;
            int d2 = n % 16;
            return HEX_DIGITS[d1] + HEX_DIGITS[d2];
        }

        public static String encode(String origin) {
            return encode(origin, CharsetUtil.UTF_8);
        }

        public static String encode(String origin, String charsetName) {
            String resultString = null;
            try {
                resultString = origin;
                MessageDigest md = MessageDigest.getInstance("MD5");
                resultString = StrUtil.isEmpty(charsetName) ? byteArrayToHexString(md.digest(resultString.getBytes()))
                        : byteArrayToHexString(md.digest(resultString.getBytes(charsetName)));
            } catch (Exception exception) {
                log.error("MD5加密失败", exception);
            }
            return resultString;
        }
    }

}
